class SRMeleeFire extends KFMeleeFire;

var const float DamageStaminaExpenceRate;
var bool bSilentWeapon;
var float InvisExpence;
var float BackStabBonus;
var class<DamageType> BleedOutDamageClass;
var bool bIsColdSteel;

var int StunAbility;

var	bool bIsSilentCritStrike;

var class<DamTypeColdSteel> DamTypeInfiltrator;

var int DamageConst,MaxAdditionalDamage;

var Actor MainTarget,LastTarget;

simulated function Timer()
{
	local Actor HitActor;
	local vector StartTrace, EndTrace, HitLocation, HitNormal;
	local rotator PointRot;
	local int MyDamage;
	local SRPlayerReplicationInfo SRPRI;
	
	SRMeleeGun(Weapon).StunAbility = Self.StunAbility;
	
	SRHumanPawn(Instigator).ConsumeStamina(WeaponStaminaCost() * 0.5);
	if ( !bSilentWeapon || !SRHumanPawn(Instigator).bInvisible )
	{
		Instigator.MakeNoise(1.0);
	}

	MeleeDamage = DamageConst + MaxAdditionalDamage;
	MyDamage = damageConst + MaxAdditionalDamage;

	If( !KFWeapon(Weapon).bNoHit )
	{
		MyDamage = MeleeDamage;
		StartTrace = Instigator.Location + Instigator.EyePosition();

		if( Instigator.Controller!=None && PlayerController(Instigator.Controller)==None && Instigator.Controller.Enemy!=None )
		{
        	PointRot = rotator(Instigator.Controller.Enemy.Location-StartTrace); // Give aimbot for bots.
        }
		else
        {
            PointRot = Instigator.GetViewRotation();
        }

		EndTrace = StartTrace + vector(PointRot)*weaponRange;
		HitActor = Instigator.Trace( HitLocation, HitNormal, EndTrace, StartTrace, true);

		if (HitActor!=None)
		{
			ImpactShakeView();

			if( HitActor.IsA('ExtendedZCollision') && HitActor.Base != none &&
                HitActor.Base.IsA('KFMonster') )
            {
                HitActor = HitActor.Base;
            }

			if ( (HitActor.IsA('KFMonster') || HitActor.IsA('KFHumanPawn')) && KFMeleeGun(Weapon).BloodyMaterial!=none )
			{
				Weapon.Skins[KFMeleeGun(Weapon).BloodSkinSwitchArray] = KFMeleeGun(Weapon).BloodyMaterial;
				Weapon.texture = Weapon.default.Texture;
			}
			if( Level.NetMode==NM_Client )
            {
                Return;
            }

//			if( HitActor.IsA('Pawn') && !HitActor.IsA('Vehicle')
//			 && (Normal(HitActor.Location-Instigator.Location) dot vector(HitActor.Rotation))<0 )
//			{
//				MyDamage*= BackStabBonus; // Backstab >:P
//			}

			MainTarget = HitActor;

			if( (KFMonster(HitActor)!=none) )
			{
				SRPRI = SRPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
				if ( SRPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.default.PerkIndex == class'SRVetPhantom'.default.PerkIndex
					&& default.DamTypeInfiltrator != none )
				{
					HitDamageClass = default.DamTypeInfiltrator;
				}
				else
				{
					HitDamageClass = default.HitDamageClass;
				}

				/*
				if ( bIsSilentCritStrike && SRHumanPawn(Instigator).bInvisible && SRPRI.ClientVeteranSkill == class'SRVetPhantom' )
				{
					AfflictTarget(HitActor,MyDamage*7.5, HitLocation, vector(PointRot),class'DamTypeNinjatoCritical');
					SRHumanPawn(Instigator).BecomeVisible();
					KFMonsterController(KFMonster(HitActor).Controller).Target = Instigator;
					KFMonsterController(KFMonster(HitActor).Controller).Enemy = Instigator;
				}
				*/
			//	else
			//	{
					AfflictTarget(HitActor,MyDamage, HitLocation, vector(PointRot), HitDamageClass);
			//	}

				if ( !bSilentWeapon )
				{
					Instigator.MakeNoise(1.0);
					if ( SRPRI.ClientVeteranSkillLevel > 9 && SRPRI.ClientVeteranSkill == class'SRVetPhantom' )
					{}//	DKGameType(Level.Game).ConsumeInvis(SRHumanPawn(Instigator).InvisController,InvisExpence);
					else
						SRHumanPawn(Instigator).BecomeVisible(); //DKGameType(Level.Game).MakeVisible(SRHumanPawn(Instigator).InvisController);
				}

            	if(MeleeHitSounds.Length > 0)
            	{
            		Weapon.PlaySound(MeleeHitSounds[Rand(MeleeHitSounds.length)],SLOT_None,MeleeHitVolume,,,,false);
            	}

				if( VSize(Instigator.Velocity) > 300 && KFMonster(HitActor).Mass <= Instigator.Mass )
				{
				    KFMonster(HitActor).FlipOver();
				}

			}
			else
			{
				AfflictTarget(HitActor,MyDamage, HitLocation, vector(PointRot), HitDamageClass);
				Spawn(HitEffectClass,,, HitLocation, rotator(HitLocation - StartTrace));
				//if( KFWeaponAttachment(Weapon.ThirdPersonActor)!=None )
		        //  KFWeaponAttachment(Weapon.ThirdPersonActor).UpdateHit(HitActor,HitLocation,HitNormal);

		        //Weapon.IncrementFlashCount(ThisModeNum);
			}
		}
		
		HurtRadius(MyDamage,WeaponRange,10000,180,HitDamageClass);
		
		LastTarget = MainTarget;
		MainTarget = none;
	}
}

function HurtRadius(float Damage, float Radius, float MomentumTransfer, float Angle, class<DamageType> DamageType);

function float WeaponStaminaCost()
{
	local KFWeapon KFW;
	local float ExpenceMod;
	
	KFW = KFWeapon(Weapon);
	
	if ( KFW == none )
		return 0.0;
		
	ExpenceMod = 1.0;
	ExpenceMod *= class<KFWeaponDamageType>(HitDamageClass).default.HeadShotDamageMult;
	
	if ( bal_ClaymoreSword(KFW) != none && ThisModeNum == 0 )
		ExpenceMod *= 2.5;
		
	if ( Knife(KFW) != none || Machete(KFW) != none || Katana1_(KFW) != none || Axe1_(KFW) != none || BlackChainsaw(KFW) != none || bal_ClaymoreSword(KFW) != none )
	{
		return ( damageConst + maxAdditionalDamage ) * ExpenceMod * DamageStaminaExpenceRate;
	}
	
	return 0.0;
}

simulated event ModeDoFire()
{
	local float Rec;

	if (!AllowFire())
		return;

	Rec = GetFireSpeed();
	SetTimer(DamagedelayMin/Rec, False);
	FireRate = default.FireRate/Rec;
	FireAnimRate = default.FireAnimRate*Rec;
	ReloadAnimRate = default.ReloadAnimRate*Rec;

	if (MaxHoldTime > 0.0)
		HoldTime = FMin(HoldTime, MaxHoldTime);

	// server
	if (Weapon.Role == ROLE_Authority)
	{
		Weapon.ConsumeAmmo(ThisModeNum, Load);
		DoFireEffect();

		HoldTime = 0;   // if bot decides to stop firing, HoldTime must be reset first
		if ( (Instigator == None) || (Instigator.Controller == None) )
			return;

		if ( AIController(Instigator.Controller) != None )
			AIController(Instigator.Controller).WeaponFireAgain(BotRefireRate, true);

		Instigator.DeactivateSpawnProtection();
	}

	// client
	if (Instigator.IsLocallyControlled())
	{
		ShakeView();
		PlayFiring();
		FlashMuzzleFlash();
		StartMuzzleSmoke();
		ClientPlayForceFeedback(FireForce);
	}
	else // server
		ServerPlayFiring();

	Weapon.IncrementFlashCount(ThisModeNum);

	// set the next firing time. must be careful here so client and server do not get out of sync
	if (bFireOnRelease)
	{
		if (bIsFiring)
			NextFireTime += MaxHoldTime + FireRate;
		else
			NextFireTime = Level.TimeSeconds + FireRate;
	}
	else
	{
		NextFireTime += FireRate;
		NextFireTime = FMax(NextFireTime, Level.TimeSeconds);
	}

	Load = AmmoPerFire;
	HoldTime = 0;

	if (Instigator.PendingWeapon != Weapon && Instigator.PendingWeapon != None)
	{
		bIsFiring = false;
		Weapon.PutDown();
	}


//	Weapon.Owner.Velocity.x *= KFMeleeGun(Weapon).ChopSlowRate;
//	Weapon.Owner.Velocity.y *= KFMeleeGun(Weapon).ChopSlowRate;
}

function bool AllowFire()
{
	local SRPlayerReplicationInfo SRPRI;
	
	SRPRI = SRPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
	
	if ( SRPRI.ClientVeteranSkill == class'SRVetPhantom' )
	{
		if ( SRHumanPawn(Instigator).bInvisible && !bIsSilentCritStrike && SRPRI.ClientVeteranSkillLevel < 10 )
			return false;
	}
	return Super.AllowFire();
}

function AfflictTarget(Actor MyTarget, float Damage, Vector HitLocation, Vector Momentum, class<DamageType> DamageType)
{
	MyTarget.TakeDamage(Damage,Instigator,HitLocation,Momentum,DamageType);
}

function float GetFireSpeed()
{
	local float ret;

	if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none )
	{
		ret = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetFireSpeedMod(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo), Weapon);
	}
	else
	{
		ret = 1.00;
	}
	
	ret *= PresetFireSpeed();

	return ret;
}

function float PresetFireSpeed()
{
	return 1.00;
}

defaultproperties
{
	MaxAdditionalDamage = 0
	DamTypeInfiltrator = None
	BackStabBonus = 2.0
	bSilentWeapon = false
	DamageStaminaExpenceRate = 0.002
	InvisExpence = 0.00
	BleedOutDamageClass = none
	StunAbility = 0
	bIsColdSteel = true
	bWaitForRelease = false
}
